package gdt.service;

import java.util.Collections;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import org.springframework.binding.message.MessageContext;
import org.springframework.security.userdetails.UserDetailsService;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import gdt.dao.AnnouncementDAO;
import gdt.entity.Announcement;
import gdt.entity.GroupAnnouncement;
import gdt.entity.Member;
import gdt.entity.Project;
import gdt.entity.ProjectAnnouncement;
import gdt.service.utils.Validator;


public class AnnouncementService {

	@Transactional(readOnly=true)
	public Announcement findById(long id){
		return announcementDao.findById(id);
	}
	
	public List<Announcement> findByUser(String username){
		Member user = (Member) userDetailsService.loadUserByUsername(username);

		List<Announcement> announcements = new LinkedList<Announcement>();
		announcements.addAll(user.getGroup().getAnnouncements());
		if(memberService.isAdmin(user)){
			for(Project p : user.getGroup().getProjects()){
				announcements.addAll(p.getAnnouncements());
			}
		}else{
			for(Project p : user.getAssignedProjects()){
				announcements.addAll(p.getAnnouncements());
			}
		}
		Collections.sort(announcements);
		return announcements;
	}
	
	@Transactional(propagation=Propagation.REQUIRED,readOnly=false)
	public boolean save(Announcement announcement, MessageContext messageContext){
		if(validate(announcement,messageContext)){
			save(announcement);
			return true;
		}
		else{
			return false;
		}
	}
	
	@Transactional(propagation=Propagation.REQUIRED,readOnly=false)
	public void save(Announcement announcement){
		announcement.setDate(new Date());
		announcement = announcementDao.makePersistent(announcement);
	}
	
	@Transactional(propagation=Propagation.REQUIRED,readOnly=false)
	public boolean delete(Announcement announcement, MessageContext messageContext){
		if(announcement instanceof ProjectAnnouncement)
			((ProjectAnnouncement) announcement).getProject().removeAnnouncement((ProjectAnnouncement) announcement);
		else
			((GroupAnnouncement) announcement).getGroup().removeAnnouncement((GroupAnnouncement) announcement);
		announcementDao.makeTransient(announcement);
		return true;
	}
	

	public ProjectAnnouncement setup(Project project){
		ProjectAnnouncement a = new ProjectAnnouncement();
		a.setProject(project);
		a.setDate(new Date());
		return a;
	}
	

	public GroupAnnouncement setup(String username){
		Member user = (Member) userDetailsService.loadUserByUsername(username);
		GroupAnnouncement a = new GroupAnnouncement();
		a.setGroup(user.getGroup());
		a.setDate(new Date());
		return a;
	}
	
	
	
	/********************************* DAO's *********************************/
	
	private AnnouncementDAO announcementDao;
	
	public void setAnnouncementDao(AnnouncementDAO announcementDao) {
		this.announcementDao = announcementDao;
	}
	
	private UserDetailsService userDetailsService;

	public void setUserDetailsService(UserDetailsService userDetailsService) {
		this.userDetailsService = userDetailsService;
	}

	
	/******************************* Service's *******************************/
	
	private MemberService memberService;

	public void setMemberService(MemberService memberService) {
		this.memberService = memberService;
	}

	/******************************* Validation *******************************/
	
	private Validator validator;
	
	public boolean validate(Announcement announcement, MessageContext context){
		return validator.validate(announcement, context);
	}
	
	public Validator getValidator() {
		return validator;
	}

	public void setValidator(Validator validator) {
		this.validator = validator;
	}
	
}
